package model.management;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import java.util.Date;
import java.util.Iterator;

import model.entity.Item;
import model.entity.Product;
import model.entity.container.ProductGroup;
import model.entity.container.StorageUnit;
import model.exceptions.InvalidNameException;
import model.exceptions.NullContainerException;

import org.junit.Before;
import org.junit.Test;

import common.Barcode;
import common.Barcode.InvalidProductBarcodeException;
import common.Result;
import common.Size;
import common.util.DateUtils;

public class ItemManagerTest
{
  StorageUnit  unit;
  ProductGroup group;

  private Item nullItem;
  private Item validItem;
  private Item invalidItem;

  @Before
  public void setUp() throws InvalidNameException, NullContainerException
  {
    ItemManager.clear();
    ProductManager.clear();
    ProductGroupManager.clear();
    StorageUnitManager.clear();

    unit = new StorageUnit("unit");
    group = new ProductGroup("group", unit, 1);

    nullItem = null;
    validItem = new Item(new Product(), new Barcode(), new Date(), new Date(), unit);
    invalidItem = new Item(new Product(), new Barcode(), new Date(), new Date(), group);
  }

  @Test
  public void testValidateAddItem()
  {

    // invalid-null Item
    Result result = ItemManager.validateAddItem(nullItem);
    assertFalse(result.getStatus());

    // invalid-invalid Item
    Result result2 = ItemManager.validateAddItem(invalidItem);
    assertFalse(result2.getStatus());

    // valid
    Result result3 = ItemManager.validateAddItem(validItem);
    assertTrue(result3.getStatus());

    // invalid-already exist
    ItemManager.addItem(validItem);
    Result result4 = ItemManager.validateAddItem(validItem);
    assertFalse(result4.getStatus());

  }

  @Test
  public void testAddItem()
  {

    // invalid
    Result result = ItemManager.addItem(nullItem);
    assertFalse(ItemManager.getItems().hasNext());
    assertFalse(result.getStatus());

    // valid
    Result result2 = ItemManager.addItem(validItem);
    Iterator<Item> itr = ItemManager.getItems();
    assertTrue(itr.hasNext());
    assertEquals(itr.next(), validItem);
    assertFalse(itr.hasNext());
    assertTrue(result2.getStatus());

  }

  @Test
  public void testValidateRemoveItem()
  {

    // invalid-null Item
    Result result = ItemManager.validateRemoveItem(nullItem);
    assertFalse(result.getStatus());

    // valid
    ItemManager.addItem(validItem);
    Result result3 = ItemManager.validateRemoveItem(validItem);
    assertTrue(result3.getStatus());

    // invalid-doesn't exist
    Result result4 = ItemManager.validateRemoveItem(validItem);
    assertFalse(result4.getStatus());

  }

  @Test
  public void testRemoveProdcut()
  {

    // invalid
    ItemManager.addItem(validItem);
    Result result = ItemManager.validateRemoveItem(nullItem);
    Iterator<Item> itr = ItemManager.getItems();
    assertTrue(itr.hasNext());
    assertEquals(itr.next(), validItem);
    assertFalse(itr.hasNext());
    assertFalse(result.getStatus());

    // valid
    Result result2 = ItemManager.addItem(validItem);
    assertFalse(ItemManager.getItems().hasNext());
    assertTrue(result2.getStatus());

  }

  @Test
  public void testUpdateProdcut() throws InvalidProductBarcodeException
  {
    Product p1 = new Product(new Barcode("700000000"), "description", new Size(), 36, 1);
    Item oldItem = new Item(p1, new Barcode(), DateUtils.currentDate(), new Date(), group);
    Item newItem = new Item(p1, new Barcode(), DateUtils.currentDate(), new Date(), unit);

    ItemManager.addItem(oldItem);

    // invalid
    Result result = ItemManager.updateItem(oldItem, nullItem);
    Iterator<Item> itr = ItemManager.getItems();
    assertTrue(itr.hasNext());
    assertEquals(itr.next(), oldItem);
    assertFalse(itr.hasNext());
    assertFalse(result.getStatus());

    // valid
    Result result2 = ItemManager.updateItem(oldItem, newItem);
    itr = ItemManager.getItems();
    assertTrue(itr.hasNext());
    assertEquals(itr.next(), newItem);
    assertFalse(itr.hasNext());
    assertTrue(result2.getStatus());

  }

}